#ifndef LGE_QUEUE_H
#define LGE_QUEUE_H

#include <core/lge_uncopyable.h>
#include <core/lge_mutex.h>
#include <core/lge_semaphore.h>
#include <queue>

template<class T>
class Queue : public Uncopyable
{
	std::queue<T> mQueue;

	mutable Mutex mQueueMutex;

	Semaphore mSyncObj;

public:
	Queue(SizeT maxSize) : mSyncObj(maxSize, 0)
	{
	}

	void push(const T & elem)
	{
		mQueueMutex.lock();
		mQueue.push(elem);
		mQueueMutex.unlock();

		// Signal that it's been changed
		while (!mSyncObj.increment());
	}

	void pop(T & elem)
	{
		// We are taking one job
		mSyncObj.decrement();

		mQueueMutex.lock();
		elem = mQueue.front();
		mQueue.pop();
		mQueueMutex.unlock();
	}

	bool empty() const
	{
		bool isEmpty;
		mQueueMutex.lock();
		isEmpty = mQueue.empty();
		mQueueMutex.unlock();
		return isEmpty;
	}

	SizeT size() const
	{
		SizeT queueSize;
		mQueueMutex.lock();
		queueSize = mQueue.size();
		mQueueMutex.unlock();
		return queueSize;
	}
};

#endif
